#pragma once

#include<iostream>
#include<string>
#include<cstring>
#include<sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "log.hpp"
#include "err.hpp"

const static int backlog=32;
const static int defaultsock=-1;
class Sock
{
    const static int backlog=32;

    public:
    Sock(int sock=defaultsock):_listensock(sock)
    {}
    void Socket()
    {
        _listensock=socket(AF_INET,SOCK_STREAM,0);//创建套接字
        if(_listensock<0)//创建失败
        {
            logMessage(FATAL,"create sock error");
            exit(SOCKET_ERR);
        }
        //创建成功
        logMessage(NORMAL,"create sock success,origin sock: %d\n",_listensock);
        int opt=1;
        setsockopt(_listensock,SOL_SOCKET,SO_REUSEADDR|SO_REUSEPORT,&opt,sizeof(opt));//允许套接字关闭后立刻重启
    } 

     void Bind(int port)
    {
        //绑定自己的网络信息
        struct sockaddr_in local;
        memset(&local,0,sizeof(local));//将结构体清空
        local.sin_family=AF_INET;//添加协议
        local.sin_port=htons(port);//添加端口号
        local.sin_addr.s_addr=htons(INADDR_ANY);//不绑定指定IP，可以接收任意IP主机发送来的数据
        //将本地设置的信息绑定到网络协议栈
        if (bind(_listensock,(struct sockaddr*)&local,sizeof(local))<0)
        {
            logMessage(FATAL,"bind socket error");
            exit(BIND_ERR);
        }
        logMessage(NORMAL,"bind socket success");
    }

     void Listen()//将套接字设置为监听
    {
        if(listen(_listensock,0)<0)
        {
            logMessage(FATAL,"listen socket error");
            exit(LISTEN_ERR);
        }
        logMessage(NORMAL,"listen socket success");
    }

     int Accpet(string * clientip,uint16_t* clientport,int*err)
    {
        logMessage(DEBUG,"enter Accept");
        *err=errno;
        struct sockaddr_in cli;
        socklen_t len= sizeof(cli);
        logMessage(DEBUG,"will accept");//拿上来连接后，第二次调用到这里，调用accept函数阻塞住了，难道不是设定了sock是非阻塞了吗？11.17.21.24
        int sock=accept(_listensock,(struct sockaddr*)&cli,&len);
        logMessage(DEBUG,"accept done");

        if(sock<0)
        {
            logMessage(FATAL,"accept error");//这里accept失败为什么不退出
        }else
        {
            logMessage(NORMAL,"accept a new link,get new sock : %d",sock);
            *clientip=inet_ntoa(cli.sin_addr);
            *clientport=ntohs(cli.sin_port);
        }
        logMessage(DEBUG,"quit Accept");
        return sock;
    }

    int Fd()
    {
        return _listensock;
    }

    private:
    int _listensock;
};